using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Imaging;
using Microsoft.Win32;
using needle.UI.Controls.Flat.Utilities;
using needle.UI.Controls.Flat.Utilities.Win32;
using needle.UI.Controls.Flat.Utilities.Drawing;
using needle.UI.Controls.Flat.Windows.Forms;
using needle.UI.Controls.Flat.Windows.Forms.Helpers;

namespace needle.UI.Controls.Flat.Windows.Docking
{
    [ToolboxItem(false)]
    public class WindowDetailCaption : WindowDetail, IMessageFilter
    {
        protected static ImageList mimages;

        public event EventHandler Close;
		public event EventHandler Restore;
		public event EventHandler InvertAutoHide;
        public event ContextEventHandler Context;

        protected ImageButton mmaxButton;
        protected ImageButton mcloseButton;
        protected ImageButton mhideButton;
        protected RedockerContent mredocker;
        protected IZoneMaximizeWindow mmaxInterface;
        protected bool mshowCloseButton;
        protected bool mshowHideButton;
        protected bool mignoreHideButton;
        protected bool mpinnedImage;

        protected static ImageAttributes mactiveAttr = new ImageAttributes();
        protected static ImageAttributes minactiveAttr = new ImageAttributes();

		#region Constructors
		
		public WindowDetailCaption(DockingManager manager, 
                                   Size fixedSize, 
                                   EventHandler closeHandler, 
                                   EventHandler restoreHandler, 
                                   EventHandler invertAutoHideHandler, 
                                   ContextEventHandler contextHandler)
            : base(manager)
        {
            DefineButtonRemapping();

            mmaxButton = null;
            mhideButton = null;
            mmaxInterface = null;
            mredocker = null;
            mshowCloseButton = true;
            mshowHideButton = true;
            mignoreHideButton = false;
            mpinnedImage = false;
            
			SetStyle(ControlStyles.DoubleBuffer | 
					 ControlStyles.AllPaintingInWmPaint |
					 ControlStyles.UserPaint, true);

            this.Size = fixedSize;

            if (closeHandler != null)
                this.Close += closeHandler;	

            if (restoreHandler != null)
                this.Restore += restoreHandler;	

            if (invertAutoHideHandler != null)
                this.InvertAutoHide += invertAutoHideHandler;
    
            if (contextHandler != null)
                this.Context += contextHandler;	

            CreateButtons();

            Application.AddMessageFilter(this);
        }

		#endregion

		#region Dispose

		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (mcloseButton != null)
				{
					mcloseButton.Click -= new EventHandler(OnButtonClose);
					mcloseButton.GotFocus -= new EventHandler(OnButtonGotFocus);
				}

				if (mhideButton != null)
				{
					mhideButton.Click -= new EventHandler(OnButtonHide);
					mhideButton.GotFocus -= new EventHandler(OnButtonGotFocus);
				}
                
				if (mmaxButton != null)
				{
					mmaxButton.Click -= new EventHandler(OnButtonMax);
					mmaxButton.GotFocus -= new EventHandler(OnButtonGotFocus);
				}
			}
			base.Dispose( disposing );
		}

		#endregion

		#region Virtuals

		protected void RecalculateMaximizeButton()
		{
			if (this.ParentZone != null)
			{
				IZoneMaximizeWindow zmw = this.ParentZone as IZoneMaximizeWindow;

				if (zmw != null)
				{
					AddMaximizeInterface(zmw);
					return;
				}
			}

			RemoveMaximizeInterface();
		}

		protected void AddMaximizeInterface(IZoneMaximizeWindow zmw)
		{
			if (mmaxInterface == null)
			{
				mmaxButton = new ImageButton(mimages, 0);

				mmaxButton.Click += new EventHandler(OnButtonMax);
				mmaxButton.GotFocus += new EventHandler(OnButtonGotFocus);

				OnAddMaximizeInterface();

				Controls.Add(mmaxButton);

				mmaxInterface = zmw;

				mmaxInterface.RefreshMaximize += new EventHandler(OnRefreshMaximize);

				RecalculateButtons();
			}
		}

		protected void RemoveMaximizeInterface()
		{
			if (mmaxInterface != null)
			{
				mmaxInterface.RefreshMaximize -= new EventHandler(OnRefreshMaximize);

				mmaxInterface = null;

				ControlUtilities.Remove(this.Controls, mmaxButton);

				OnRemoveMaximizeInterface();

				mmaxButton.Click -= new EventHandler(OnButtonMax);
				mmaxButton.GotFocus -= new EventHandler(OnButtonGotFocus);

				mmaxButton.Dispose();
				mmaxButton = null;

				RecalculateButtons();
			}
		}

		protected void OnRefreshMaximize(object sender, EventArgs e)
		{
			UpdateMaximizeImage();
		}
	
		protected void OnButtonMax(object sender, EventArgs e)
		{
			if (this.ParentWindow != null)
			{
				if (mmaxInterface.IsMaximizeAvailable())
				{
					if (mmaxInterface.IsWindowMaximized(this.ParentWindow))
						mmaxInterface.RestoreWindow();
					else
						mmaxInterface.MaximizeWindow(this.ParentWindow);
				}
			}			
		}

		protected void OnButtonClose(Object sender, EventArgs e)
		{
			if (mshowCloseButton)
				OnClose();
		}

		protected void OnButtonHide(Object sender, EventArgs e)
		{
			if (mshowHideButton && !mignoreHideButton)
				OnInvertAutoHide();
		}

		protected void OnButtonGotFocus(Object sender, EventArgs e)
		{
			if (this.ParentWindow != null)
				this.ParentWindow.WindowDetailGotFocus(this);
		}

		protected virtual void DefineButtonRemapping() {}
		protected virtual void OnAddMaximizeInterface() {}
		protected virtual void OnRemoveMaximizeInterface() {}
		protected virtual void UpdateMaximizeImage() {}
		protected virtual void UpdateAutoHideImage() {}
		protected virtual void RecalculateButtons() {}
        
		protected virtual void CreateButtons() 
		{
			if (mcloseButton != null)
			{
				mcloseButton.Click += new EventHandler(OnButtonClose);
				mcloseButton.GotFocus += new EventHandler(OnButtonGotFocus);
			}

			if (mhideButton != null)
			{
				mhideButton.Click += new EventHandler(OnButtonHide);
				mhideButton.GotFocus += new EventHandler(OnButtonGotFocus);
			}
		}

		public virtual void OnClose()
        {
            if (Close != null)
                Close(this, EventArgs.Empty);
        }

        public virtual void OnInvertAutoHide()
        {
            if (InvertAutoHide != null)
                InvertAutoHide(this, EventArgs.Empty);
        }
        
        public virtual void OnRestore()
        {
            if (Restore != null)
                Restore(this, EventArgs.Empty);
        }

        public virtual void OnContext(Point screenPos)
        {
            if (Context != null)
                Context(this,new ContextEventArgs(screenPos));
        }

		#endregion

		#region Overrides

        public override void NotifyAutoHideImage(bool autoHidden)
        {
            mpinnedImage = autoHidden;
            UpdateAutoHideImage();
        }

        public override void NotifyCloseButton(bool show)
        {
            mshowCloseButton = show;
            RecalculateButtons();
        }

        public override void NotifyHideButton(bool show)
        {
            mignoreHideButton = (mparentWindow.State == State.Floating);
            
            mshowHideButton = show;
            RecalculateButtons();
        }

        public override void NotifyShowCaptionBar(bool show)
        {
            this.Visible = show;
        }
       

		protected override void OnDoubleClick(EventArgs e)
		{
            if (!IsDisposed)
            {
                if (mredocker != null)
                {
                    mredocker = null;
                }
            }

			OnRestore();
		}

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (!IsDisposed)
            {
				if (mredocker != null)
				{
					mredocker.QuitTrackingMode(e);

					mredocker = null;
				}
				else
				{
					if (e.Button == MouseButtons.Left)
					{
						if (this.ParentWindow.RedockAllowed)
						{
							WindowContent wc = this.ParentWindow as WindowContent;

							if (wc != null)
							{
								mredocker = new RedockerContent(this, wc, new Point(e.X, e.Y));
							}
						}
					}

					this.Focus();
				}
            }
            
            base.OnMouseDown(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (!IsDisposed)
            {
                if (mredocker != null)
                    mredocker.OnMouseMove(e);
            }

            base.OnMouseMove(e);
        }

		protected override void OnMouseUp(MouseEventArgs e)
        {
            if (!IsDisposed)
            {
                if (mredocker != null)
                {
                    mredocker.OnMouseUp(e);

                    mredocker = null;
                }

                if (e.Button == MouseButtons.Right)
                {
					Point pt = this.PointToScreen(new Point(e.X, e.Y));
    				
					OnContext(pt);
                }
            }
            
            base.OnMouseUp(e);
        }

        protected override void OnResize(EventArgs e)
        {
            Invalidate();
            base.OnResize(e);
        }

		#endregion

		#region Methods

		[UseApiElements("VK_ESCAPE, WM_KEYDOWN")]
		public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == (int)Msgs.WM_KEYDOWN)
            {
                if ((int)m.WParam == (int)VirtualKeys.VK_ESCAPE)
                {                   
                    if (mredocker != null)
                    {
                        mredocker.QuitTrackingMode(null);

                        mredocker = null;
                        
                        return true;
                    }
                }
            }
            
            return false;
        }

		#endregion

		#region Properties

		public override Zone ParentZone
		{
			get { return base.ParentZone; }
			set
			{
				base.ParentZone = value;

				RecalculateMaximizeButton();
				RecalculateButtons();
			}
		}

		#endregion
    }

    [ToolboxItem(false)]
    public class WindowDetailCaptionPlain : WindowDetailCaption
    {
		#region Nested types

		protected enum ImageIndex
        {
            Close					= 0,
            EnabledHorizontalMax	= 1,
            EnabledHorizontalMin	= 2,
            EnabledVerticalMax		= 3,
            EnabledVerticalMin		= 4, 
            AutoHide		        = 5, 
            AutoShow		        = 6 
        }

		#endregion

        protected const int minset = 3;
        protected const int moffset = 5;
        protected const int mfixedLength = 14;
        protected const int mimageWidth = 10;
        protected const int mimageHeight = 10;
        protected const int mbuttonWidth = 12;
        protected const int mbuttonHeight = 12;
        protected const int minsetButton = 2;

        protected bool mdockLeft;
        protected int mbuttonOffset;

		#region Constructors
		
		static WindowDetailCaptionPlain()
        {
            mimages = DrawHelpers.LoadBitmapStrip(Type.GetType("needle.UI.Controls.Flat.Windows.Docking.WindowDetailCaptionPlain"),
                                                     "needle.UI.Controls.Flat.Windows.Forms.Resources.ImagesCaptionPlain.bmp",
                                                     new Size(mimageWidth, mimageHeight),
                                                     new Point(0,0));
        }

        public WindowDetailCaptionPlain(DockingManager manager, 
                                        EventHandler closeHandler, 
                                        EventHandler restoreHandler, 
                                        EventHandler invertAutoHideHandler, 
                                        ContextEventHandler contextHandler)
            : base(manager, 
                   new Size(mfixedLength, mfixedLength), 
                   closeHandler, 
                   restoreHandler, 
                   invertAutoHideHandler, 
                   contextHandler)
        {
            mdockLeft = true;
            mbuttonOffset = 1 + (mbuttonWidth + minsetButton) * 2;
        }

		#endregion

		#region Overrides
        
        public override void ParentStateChanged(State newState)
        {
            switch(newState)
            {
                case State.DockTop:
                case State.DockBottom:
                    mdockLeft = true;
                    break;
                case State.Floating:
                case State.DockLeft:
                case State.DockRight:
                    mdockLeft = false;
                    break;
            }

            mignoreHideButton = (mparentWindow.State == State.Floating);

            RecalculateButtons();
        }

        public override void RemovedFromParent(Window parent)
        {
            if (parent != null)
            {
                if (this.Dock != DockStyle.None)
                {
                    Size minSize = parent.MinimalSize;

                    if (this.Dock == DockStyle.Left)
                    {
                        minSize.Width -= mfixedLength;
                    }
                    else
                    {
                        minSize.Height -= mfixedLength;
                    }

                    parent.MinimalSize = minSize;
                }
            }
        }

        public override void AddedToParent(Window parent)
        {
            if (parent != null)
            {
                if (this.Dock != DockStyle.None)
                {
                    Size minSize = parent.MinimalSize;

                    if (this.Dock == DockStyle.Left)
                    {
                        minSize.Width += mfixedLength;
                    }
                    else
                    {
                        minSize.Height += mfixedLength;
                    }

                    parent.MinimalSize = minSize;
                }
            }
        }
        
        protected override void DefineButtonRemapping()
        {
            ColorMap activeMap = new ColorMap();
            ColorMap inactiveMap = new ColorMap();
			
            activeMap.OldColor = Color.Black;
            activeMap.NewColor = mmanager.InactiveTextColor;
            inactiveMap.OldColor = Color.Black;
            inactiveMap.NewColor = Color.FromArgb(128, mmanager.InactiveTextColor);

            mactiveAttr.SetRemapTable(new ColorMap[]{activeMap}, ColorAdjustType.Bitmap);
            minactiveAttr.SetRemapTable(new ColorMap[]{inactiveMap}, ColorAdjustType.Bitmap);
        }

        protected override void OnAddMaximizeInterface()
        {
            if (mmaxButton != null)
            {
                mmaxButton.Size = new Size(mbuttonWidth, mbuttonHeight);

                mbuttonOffset += (mbuttonWidth + minsetButton);
            }
        }

        protected override void OnRemoveMaximizeInterface()
        {
            mbuttonOffset -= (mbuttonWidth + minsetButton);
        }

        protected override void CreateButtons()
        {
            mcloseButton = new ImageButton(mimages, (int)ImageIndex.Close);
            mhideButton = new ImageButton(mimages, (int)ImageIndex.AutoHide);
			
            mcloseButton.Size = new Size(mbuttonWidth, mbuttonHeight);
            mhideButton.Size = new Size(mbuttonWidth, mbuttonHeight);

            Controls.Add(mcloseButton);
            Controls.Add(mhideButton);
            
            base.CreateButtons();
        }

        protected override void UpdateAutoHideImage()
        {
            if (mpinnedImage)
                mhideButton.ImageIndexEnabled = (int)ImageIndex.AutoShow;
            else
                mhideButton.ImageIndexEnabled = (int)ImageIndex.AutoHide;
        }
        
        protected override void UpdateMaximizeImage()
        {

            if (mmaxButton != null)
            {
                bool maximized = mmaxInterface.IsWindowMaximized(this.ParentWindow);

                if (mmaxInterface.Direction == Direction.Vertical)
                {
                    if (maximized)
                        mmaxButton.ImageIndexEnabled = (int)ImageIndex.EnabledVerticalMin;	
                    else
                        mmaxButton.ImageIndexEnabled = (int)ImageIndex.EnabledVerticalMax;	
                }
                else
                {
                    if (maximized)
                        mmaxButton.ImageIndexEnabled = (int)ImageIndex.EnabledHorizontalMin;	
                    else
                        mmaxButton.ImageIndexEnabled = (int)ImageIndex.EnabledHorizontalMax;	
                }
            }
        }

        protected override void RecalculateButtons()
        {
            if (mdockLeft)
            {
                if (this.Dock != DockStyle.Left)
                {
                    RemovedFromParent(this.ParentWindow);
                    this.Dock = DockStyle.Left;
                    AddedToParent(this.ParentWindow);
                }

                int iStart = minset;

                mcloseButton.Location = new Point(minsetButton, iStart);
                mcloseButton.Anchor = AnchorStyles.Top;
                mcloseButton.Show();
                iStart += mbuttonHeight + minsetButton;
                
                mhideButton.Location = new Point(minsetButton, iStart);
                mhideButton.Anchor = AnchorStyles.Top;
                mhideButton.Show();
                iStart += mbuttonHeight + minsetButton;

                if (mmaxButton != null)
                {
                    mmaxButton.Location = new Point(minsetButton, iStart);
                    mmaxButton.Anchor = AnchorStyles.Top;
                }
            }
            else
            {
                if (this.Dock != DockStyle.Top)
                {
                    RemovedFromParent(this.ParentWindow);
                    this.Dock = DockStyle.Top;
                    AddedToParent(this.ParentWindow);
                }

                Size client = this.ClientSize;
                int iStart = minset;

                mcloseButton.Location = new Point(client.Width - iStart - mbuttonWidth, minsetButton);
                mcloseButton.Anchor = AnchorStyles.Right;
                mcloseButton.Show();
                iStart += mbuttonWidth + minsetButton;
                
                mhideButton.Location = new Point(client.Width - iStart - mbuttonWidth, minsetButton);
                mhideButton.Anchor = AnchorStyles.Right;
                mhideButton.Show();
                iStart += mbuttonWidth + minsetButton;

                if (mmaxButton != null)
                {
                    mmaxButton.Location = new Point(client.Width - iStart - mbuttonWidth, minsetButton);
                    mmaxButton.Anchor = AnchorStyles.Right;
                }
            }

            UpdateMaximizeImage();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Size ourSize = this.ClientSize;
            Point[] light = new Point[4];
            Point[] dark = new Point[4];
				
            if (mdockLeft)
            {
                int iBottom = ourSize.Height - minset - 1;
                int iRight = moffset + 2;
                int iTop = minset + mbuttonOffset;

                light[3].X = light[2].X = light[0].X = moffset;
                light[2].Y = light[1].Y = light[0].Y = iTop;
                light[1].X = moffset + 1;
                light[3].Y = iBottom;
			
                dark[2].X = dark[1].X = dark[0].X = iRight;
                dark[3].Y = dark[2].Y = dark[1].Y = iBottom;
                dark[0].Y = iTop;
                dark[3].X = iRight - 1;
            }
            else
            {
                int iBottom = moffset + 2;
                int iRight = ourSize.Width - (minset + mbuttonOffset);
				
                light[3].X = light[2].X = light[0].X = minset;
                light[1].Y = light[2].Y = light[0].Y = moffset;
                light[1].X = iRight;
                light[3].Y = moffset + 1;
			
                dark[2].X = dark[1].X = dark[0].X = iRight;
                dark[3].Y = dark[2].Y = dark[1].Y = iBottom;
                dark[0].Y = moffset;
                dark[3].X = minset;
            }

            using (Pen lightPen = new Pen(ControlPaint.LightLight(mmanager.BackColor)),
                       darkPen = new Pen(ControlPaint.Dark(mmanager.BackColor)))
            {
                e.Graphics.DrawLine(lightPen, light[0], light[1]);
                e.Graphics.DrawLine(lightPen, light[2], light[3]);
                e.Graphics.DrawLine(darkPen, dark[0], dark[1]);
                e.Graphics.DrawLine(darkPen, dark[2], dark[3]);

                if (mdockLeft)
                {
                    for(int i=0; i<4; i++)
                    {
                        light[i].X += 4;
                        dark[i].X += 4;
                    }
                }
                else
                {
                    for(int i=0; i<4; i++)
                    {
                        light[i].Y += 4;
                        dark[i].Y += 4;
                    }
                }

                e.Graphics.DrawLine(lightPen, light[0], light[1]);
                e.Graphics.DrawLine(lightPen, light[2], light[3]);
                e.Graphics.DrawLine(darkPen, dark[0], dark[1]);
                e.Graphics.DrawLine(darkPen, dark[2], dark[3]);
            }

            base.OnPaint(e);
        }

		#endregion
    }

    public class WindowDetailCaptionIde : WindowDetailCaption
    {
		#region Nested types

		protected enum ImageIndex
        {
            Close					= 0,
            EnabledVerticalMax		= 1,
            EnabledVerticalMin		= 2,
            AutoHide		        = 3, 
            AutoShow		        = 4 
        }

		#endregion

        protected const int myInset = 3;
        protected const int myInsetExtra = 3;
        protected const int mimageWidth = 12;
        protected const int mimageHeight = 11;
        protected const int mbuttonWidth = 14;
        protected const int mbuttonHeight = 13;
        protected const int mbuttonSpacer = 3;

        protected static int mfixedLength;
        
		#region Constructors
		
		static WindowDetailCaptionIde()
        {
            mimages = DrawHelpers.LoadBitmapStrip(Type.GetType("needle.UI.Controls.Flat.Windows.Docking.WindowDetailCaptionIde"),
                                                     "needle.Controls.Flat.Windows.Forms.Resources.ImagesCaptionIDE.bmp",
                                                     new Size(mimageWidth, mimageHeight),
                                                     new Point(0,0));
        }

        public WindowDetailCaptionIde(DockingManager manager, 
                                      EventHandler closeHandler, 
                                      EventHandler restoreHandler, 
                                      EventHandler invertAutoHideHandler, 
                                      ContextEventHandler contextHandler)
            : base(manager, 
                   new Size(mfixedLength, mfixedLength), 
                   closeHandler, 
                   restoreHandler, 
                   invertAutoHideHandler,
                   contextHandler)
        {
            UpdateCaptionHeight(manager.CaptionFont);
        }

		#endregion

		#region Overrides

		public override void PropogateNameValue(PropogateName name, object value)
        {
            base.PropogateNameValue(name, value);
        
            switch(name)
            {
                case PropogateName.CaptionFont:
                    UpdateCaptionHeight((Font)value);    
                    break;
                case PropogateName.ActiveTextColor:
                case PropogateName.InactiveTextColor:
                    DefineButtonRemapping();
                    Invalidate();
                    break;
            }
        }
        
        public override void WindowGotFocus()
        {
            SetButtonState();
            Invalidate();
        }

        public override void WindowLostFocus()
        {
            SetButtonState();
            Invalidate();
        }
      
        public override void NotifyFullTitleText(string title)
        {
            this.Text = title;
            Invalidate();
        }

        public override void ParentStateChanged(State newState)
        { 
            mignoreHideButton = (mparentWindow.State == State.Floating);

            this.Dock = DockStyle.Top;
            RecalculateButtons();
            Invalidate();
        }

        public override void RemovedFromParent(Window parent)
        {
            if (parent != null)
            {
                Size minSize = parent.MinimalSize;

                minSize.Height -= mfixedLength;
                minSize.Width -= mfixedLength;

                parent.MinimalSize = minSize;
            }
        }

        protected override void DefineButtonRemapping()
        {
            ColorMap activeMap = new ColorMap();
            ColorMap inactiveMap = new ColorMap();
			
            activeMap.OldColor = Color.Black;
            activeMap.NewColor = mmanager.ActiveTextColor;
            inactiveMap.OldColor = Color.Black;
            inactiveMap.NewColor = mmanager.InactiveTextColor;

            mactiveAttr.SetRemapTable(new ColorMap[]{activeMap}, ColorAdjustType.Bitmap);
            minactiveAttr.SetRemapTable(new ColorMap[]{inactiveMap}, ColorAdjustType.Bitmap);
        }

        public override void AddedToParent(Window parent)
        {
            if (parent != null)
            {
                Size minSize = parent.MinimalSize;

                minSize.Height += mfixedLength;
                minSize.Width += mfixedLength;

                parent.MinimalSize = minSize;
            }
        }

        protected override void OnAddMaximizeInterface()
        {
            if (mmaxButton != null)
            {
                mmaxButton.Size = new Size(mbuttonWidth, mbuttonHeight);

                mmaxButton.BackColor = this.BackColor;

                SetButtonState();
            }
        }

        protected override void UpdateAutoHideImage()
        {
            if (mpinnedImage)
                mhideButton.ImageIndexEnabled = (int)ImageIndex.AutoShow;
            else
                mhideButton.ImageIndexEnabled = (int)ImageIndex.AutoHide;
        }

        protected override void UpdateMaximizeImage()
        {
            if ((mmaxButton != null) && (mmaxInterface != null))
            {
                bool enabled = mmaxInterface.IsMaximizeAvailable();

                if (!enabled)
                {
                    if (mmaxButton.Visible)
                        mmaxButton.Hide();
                }
                else
                {
                    bool maximized = mmaxInterface.IsWindowMaximized(this.ParentWindow);

                    if (!mmaxButton.Visible)
                        mmaxButton.Show();

                    if (maximized)
                        mmaxButton.ImageIndexEnabled = (int)ImageIndex.EnabledVerticalMin;	
                    else
                        mmaxButton.ImageIndexEnabled = (int)ImageIndex.EnabledVerticalMax;	
                }
            }
        }

		protected override void RecalculateButtons()
		{
			int buttonX = this.Width - mbuttonWidth - mbuttonSpacer;
			int buttonY = (mfixedLength - myInset * 2 - mbuttonHeight) / 2 + myInset;
        
			if (mshowCloseButton)
			{
				mcloseButton.Location = new Point(buttonX, buttonY);

				mcloseButton.Size = new Size(mbuttonWidth, mbuttonHeight);
    		
				mcloseButton.Anchor = AnchorStyles.Right;

				mcloseButton.Show();
                
				buttonX -= mbuttonWidth;
			}
			else
				mcloseButton.Hide();
                        
			if (mshowHideButton && !mignoreHideButton)
			{
				mhideButton.Location = new Point(buttonX, buttonY);

				mhideButton.Size = new Size(mbuttonWidth, mbuttonHeight);
			
				mhideButton.Anchor = AnchorStyles.Right;

				mhideButton.Show();

				buttonX -= mbuttonWidth;
                
				UpdateAutoHideImage();
			}
			else
				mhideButton.Hide();
            
			if (mmaxButton != null)
			{
				mmaxButton.Location = new Point(buttonX, buttonY);

				mmaxButton.Size = new Size(mbuttonWidth, mbuttonHeight);
			
				mmaxButton.Anchor = AnchorStyles.Right;

				buttonX -= mbuttonWidth;

				UpdateMaximizeImage();
			}
		}

		protected override void CreateButtons()
		{
			mcloseButton = new ImageButton(mimages, (int)ImageIndex.Close);
			mhideButton = new ImageButton(mimages, (int)ImageIndex.AutoHide);
			
			mcloseButton.Size = new Size(mbuttonWidth, mbuttonHeight);
			mhideButton.Size = new Size(mbuttonWidth, mbuttonHeight);

			mcloseButton.Anchor = AnchorStyles.Right;
			mhideButton.Anchor = AnchorStyles.Right;

			mcloseButton.Location = new Point(mfixedLength - mbuttonWidth - mbuttonSpacer, 
				(mfixedLength - myInset * 2 - mbuttonHeight) / 2 + myInset);
            
			mhideButton.Location = new Point(mfixedLength - (mbuttonWidth - mbuttonSpacer) * 2, 
				(mfixedLength - myInset * 2 - mbuttonHeight) / 2 + myInset);

			mcloseButton.BackColor = this.BackColor;
			mhideButton.BackColor = this.BackColor;

			Controls.Add(mcloseButton);
			Controls.Add(mhideButton);

			base.CreateButtons();
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			bool focused = false;

			if (this.ParentWindow != null)
				focused = this.ParentWindow.ContainsFocus;

			UpdateMaximizeImage();

			SetButtonState();
            
			Size ourSize = this.ClientSize;

			int xEnd = ourSize.Width;
			int yEnd = ourSize.Height - myInset * 2;

			Rectangle rectCaption = new Rectangle(0, myInset, xEnd, yEnd - myInset + 1);

			using(SolidBrush backBrush = new SolidBrush(this.BackColor),
					  activeBrush = new SolidBrush(mmanager.ActiveColor),
					  activeTextBrush = new SolidBrush(mmanager.ActiveTextColor),
					  inactiveBrush = new SolidBrush(mmanager.InactiveTextColor))
			{
				if (focused)
				{
					e.Graphics.FillRectangle(backBrush, e.ClipRectangle);
    	
					e.Graphics.FillRectangle(activeBrush, rectCaption);
    			
					rectCaption.X += mbuttonSpacer;
					rectCaption.Y += 1;
					rectCaption.Height -= 2;

					rectCaption.Width -= mcloseButton.Width + mbuttonSpacer;

					if ((mmaxButton != null) && (mmaxButton.Visible))
						rectCaption.Width -= mcloseButton.Width;
    				
					e.Graphics.DrawString(this.Text, mmanager.CaptionFont, activeTextBrush, rectCaption);
				}
				else
				{
					e.Graphics.FillRectangle(backBrush, e.ClipRectangle);
    	            
					using (Pen dark = new Pen(ControlPaint.LightLight(mmanager.InactiveTextColor)))
					{
						e.Graphics.DrawLine(dark, 1, myInset, xEnd - 2, myInset);
						e.Graphics.DrawLine(dark, 1, yEnd, xEnd - 2, yEnd);
						e.Graphics.DrawLine(dark, 0, myInset + 1, 0, yEnd - 1);
						e.Graphics.DrawLine(dark, xEnd - 1, myInset + 1, xEnd - 1, yEnd - 1);

						rectCaption.X += mbuttonSpacer;
						rectCaption.Y += 1;
						rectCaption.Height -= 2;

						rectCaption.Width -= mcloseButton.Width + mbuttonSpacer;

						if ((mmaxButton != null) && (mmaxButton.Visible))
							rectCaption.Width -= mmaxButton.Width;

						e.Graphics.DrawString(this.Text, mmanager.CaptionFont, inactiveBrush, rectCaption);
					}
				}	
			}
            
			base.OnPaint(e);

			mcloseButton.Refresh();
		}				

		#endregion

		#region Virtuals
		
		protected void SetButtonState()
        {
            if (this.ParentWindow != null)
            {
                if (this.ParentWindow.ContainsFocus)
                {
                    if (mcloseButton.BackColor != mmanager.ActiveColor)
                    {
                        mcloseButton.BackColor = mmanager.ActiveColor;
                        mcloseButton.Invalidate();
                    }

                    if (mhideButton != null)
                    {
                        if (mhideButton.BackColor != mmanager.ActiveColor)
                        {
                            mhideButton.BackColor = mmanager.ActiveColor;
                            mhideButton.Invalidate();
                        }
                    }

                    if (mmaxButton != null)
                    {
                        if (mmaxButton.BackColor != mmanager.ActiveColor)
                        {
                            mmaxButton.BackColor = mmanager.ActiveColor;
                            mmaxButton.Invalidate();
                        }
                    }
                }
                else
                {
                    if (mcloseButton.BackColor != this.BackColor)
                    {
                        mcloseButton.BackColor = this.BackColor;
                        mcloseButton.Invalidate();
                    }

                    if (mhideButton != null)
                    {
                        if (mhideButton.BackColor != this.BackColor)
                        {
                            mhideButton.BackColor = this.BackColor;
                            mhideButton.Invalidate();
                        }
                    }

                    if (mmaxButton != null)
                    {
                        if (mmaxButton.BackColor != this.BackColor)
                        {
                            mmaxButton.BackColor = this.BackColor;
                            mmaxButton.Invalidate();
                        }
                    }
                }
            }
        }

		protected void UpdateCaptionHeight(Font captionFont)
		{
            mfixedLength = (int)captionFont.GetHeight() + (myInset + myInsetExtra) * 2;
    
            int minHeight = mbuttonHeight + myInset * 4 + 1;

            if (mfixedLength < minHeight)
                mfixedLength = minHeight;

			this.Size = new Size(mfixedLength, mfixedLength);
			
			RecalculateButtons();

			Invalidate();
		}

		#endregion
    }
}